﻿using Microsoft.AspNetCore.SignalR;
using MultiAgentsClient.ChatDataStructures;
using MultiAgentsClient.Shared;
using MultiAgentsServer.Scripts.Services;
using MultiAgentsServer.Scripts.Services.DataModels;
using MultiAgentsShared;
using static MultiAgentsServer.Scripts.Services.BehaviorTreeService;
namespace MultiAgentsServer.Scripts.Hubs;

public class SignalRWorkflowHub(IEventBus eventBus) : SignalRBaseHub(eventBus)
{
    #region ApiRequest
    public void SendSessionId(Dictionary<string, object> requestParams)
    {
        var sessionId = requestParams.GetData<string>("sessionId");
        var userId = requestParams.GetData<int>("userId");

        _eventBus.Publish(new SaveSessionIdCommand(Context.ConnectionId, sessionId, userId, UserCookieDataModel.HubConnectionClassEnum.Workflow));
    }

    public void LlmNodeRequest(Dictionary<string, object> requestParams)
    {
        var sessionId = requestParams.GetData<string>("sessionId");
        var nodeId = requestParams.GetData<string>("nodeId");
        var msgs = requestParams.GetData<List<string>>("msgs");
        var model = requestParams.GetData<string>("model");
        var temperature = requestParams.GetData<float>("temperature");

        List<LlmMessageSimp> llmMsgsSimp = [];

        foreach (string msgJson in msgs)
        {
            llmMsgsSimp.Add(SerializableObjectBase.FromJson<LlmMessageSimp>(msgJson));
        }

        _eventBus.Publish(
            new ServerNodeLlmRequest
            {
                SessionId = sessionId,
                NodeId = nodeId,
                ConnectionId = Context.ConnectionId,
                messages = llmMsgsSimp,
                Model = model,
                temperature = temperature,
            });
    }

    public void LLMSwitchNodeRequest(Dictionary<string, object> requestParams)
    {
        var sessionId = requestParams.GetData<string>("sessionId");
        var userId = requestParams.GetData<int>("userId");
        var nodeId = requestParams.GetData<string>("nodeId");
        var message = requestParams.GetData<string>("message");
        var categories = requestParams.GetData<List<string>>("categories");

        _eventBus.Publish(new ServerNodeLLMSwitchRequestCommand(Context.ConnectionId, sessionId, userId, nodeId, message, categories) { });
    }

    public void CreateNewWorkflowRequest(Dictionary<string, object> requestParams)
    {
        var sessionId = requestParams.GetData<string>("sessionId");
        var userId = requestParams.GetData<int>("userId");
        var workflowIdName = requestParams.GetData<string>("workflowIdName");
        var workflowJson = requestParams.GetData<string>("workflowJson");

        _eventBus.Publish(new CreateNewWorkflowCommand(Context.ConnectionId, sessionId, userId, workflowIdName, workflowJson));
    }

    public void UpdateWorkflowRequest(Dictionary<string, object> requestParams)
    {
        var sessionId = requestParams.GetData<string>("sessionId");
        var userId = requestParams.GetData<int>("userId");
        var workflowId = requestParams.GetData<int>("workflowId");
        var workflowIdName = requestParams.GetData<string>("workflowIdName");
        var workflowJson = requestParams.GetData<string>("workflowJson");

        _eventBus.Publish(new UpdateWorkflowCommand(Context.ConnectionId, sessionId, userId, workflowId, workflowIdName, workflowJson));
    }

    public void RemoveWorkflowRequest(Dictionary<string, object> requestParams)
    {
        var sessionId = requestParams.GetData<string>("sessionId");
        var userId = requestParams.GetData<int>("userId");
        var workflowId = requestParams.GetData<int>("workflowId");

        _eventBus.Publish(new RemoveWorkflowCommand(Context.ConnectionId, sessionId, userId, workflowId));
    }

    public void GetAllWorkflowsByUserRequest(Dictionary<string, object> requestParams)
    {
        var sessionId = requestParams.GetData<string>("sessionId");
        var userId = requestParams.GetData<int>("userId");

        _eventBus.Publish(new GetAllWorkflowsByUserCommand(Context.ConnectionId, sessionId, userId));
    }

    public void SubscriptonUserRequest(Dictionary<string, object> requestParams)
    {
        var sessionId = requestParams.GetData<string>("sessionId");
        var userId = requestParams.GetData<int>("userId");
        var workflowId = requestParams.GetData<int>("workflowId");
        var repositoryURL = requestParams.GetData<string>("repositoryURL");
        var shouldAskMe = requestParams.GetData<bool>("shouldAskMe");

        _eventBus.Publish(new SubscriptonGitlabPullRequestCommand(Context.ConnectionId, sessionId, userId, workflowId, repositoryURL, shouldAskMe));
    }

    public void WorkflowProccessedRequest(Dictionary<string, object> requestParams)
    {
        var sessionId = requestParams.GetData<string>("sessionId");
        var userId = requestParams.GetData<int>("userId");
        var notificationId = requestParams.GetData<int>("notificationId");

        _eventBus.Publish(new WorkflowProccessedRequestCommand(Context.ConnectionId, sessionId, userId, notificationId));
    }
    
    public void LoadWorkflowByShareCodeRequest(Dictionary<string, object> requestParams)
    {
        var sessionId = requestParams.GetData<string>("sessionId");
        var userId = requestParams.GetData<int>("userId");
        var workflowJson = requestParams.GetData<string>("workflowJson");

        _eventBus.Publish(new LoadWorkflowByJsonRequestCommand(Context.ConnectionId, sessionId, userId, workflowJson));
    }
    
    public void ParameterExtractionNodeRequest(Dictionary<string, object> requestParams)
    {
        var sessionId = requestParams.GetData<string>("sessionId");
        var userId = requestParams.GetData<int>("userId");
        var nodeId = requestParams.GetData<string>("nodeId");
        var context = requestParams.GetData<string>("context");
        var descriptions = requestParams.GetData<List<string>>("descriptions");

        _eventBus.Publish(new ServerNodeParameterExtractionRequestCommand(Context.ConnectionId, sessionId, userId, nodeId, context, descriptions));
    }
    #endregion Requests

    #region ApiResponse
    //API Response
    public static async Task LlmNodeResponse(IHubContext<SignalRWorkflowHub> hubContext, string connectionId, string nodeId, string llmResponse)
    {
        await hubContext.Clients.Client(connectionId).SendAsync("LlmNodeResponse", nodeId, llmResponse);
    }

    public static async Task CreateNewWorkflowResponse(IHubContext<SignalRWorkflowHub> hubContext, string connectionId, 
        int workflowId, int userId, string workflowName, string workflowJson)
    {
        await hubContext.Clients.Client(connectionId).SendAsync("CreateNewWorkflowResponse", workflowId, userId, workflowName, workflowJson);
    }

    public static async Task UpdateWorkflowResponse(IHubContext<SignalRWorkflowHub> hubContext, string connectionId, 
        int workflowId, int userId, string workflowName, string workflowJson)
    {
        await hubContext.Clients.Client(connectionId).SendAsync("UpdateWorkflowResponse", workflowId, userId, workflowName, workflowJson);
    }

    public static async Task RemoveWorkflowResponse(IHubContext<SignalRWorkflowHub> hubContext, string connectionId, int workflowId)
    {
        await hubContext.Clients.Client(connectionId).SendAsync("RemoveWorkflowResponse", workflowId);
    }

    public static async Task GetAllWorkflowsByUserResponse(IHubContext<SignalRWorkflowHub> hubContext, string connectionId, List<Workflow> workflows)
    {
        List<string> workflowsJson = workflows.Select(workflow => workflow.ConvertToJson()).ToList();
        await hubContext.Clients.Client(connectionId).SendAsync("GetAllWorkflowResponse", workflowsJson);
    }

    public static async Task SendSystematicNotification(IHubContext<SignalRWorkflowHub> hubContext, string connectionId, List<WorkflowNotification> notificationsList)
    {
        List<string> notificationsListJson = notificationsList.Select(notification => notification.ConvertToJson()).ToList();
        await hubContext.Clients.Client(connectionId).SendAsync("RecieveSystematicNotification", notificationsListJson);
    }

    public static async Task ServerNodeLLMSwitchApiResponse(IHubContext<SignalRWorkflowHub> hubContext, string connectionId, string nodeId, string result)
    {
        await hubContext.Clients.Client(connectionId).SendAsync("NodeLLMSwitchApiResponse", nodeId, result);
    }

    public static async Task ServerNodeParameterExtractionApiResponse(IHubContext<SignalRWorkflowHub> hubContext, string connectionId, string nodeId, List<string> values)
    {
        await hubContext.Clients.Client(connectionId).SendAsync("NodeParameterExtractionApiResponse", nodeId, values);
    }
    #endregion

    #region ConnectionRelated
    // This method is called whenever a client disconnects from the hub
    public override Task OnDisconnectedAsync(Exception? exception)
    {
        _eventBus.Publish(new RemoveConnectionCommand(Context.ConnectionId));
        return base.OnDisconnectedAsync(exception);
    }
    #endregion
}
